import { IFace } from '@amcax/base';
import { isArray } from 'lodash';

/**
 * 判断边是否唯一,不唯一则添加到edges中
 * @param start 边起点索引
 * @param end 边终点索引
 * @param edges Set<String> 存储边的集合
 * @returns 是否唯一
 */
const isUniqueEdge = (start: number, end: number, edges: Set<string>) => {
  const hash1 = `${start}-${end}`;
  const hash2 = `${end}-${start}`;
  if (edges.has(hash1) || edges.has(hash2)) {
    return false;
  } else {
    edges.add(hash1);
    edges.add(hash2);
    return true;
  }
};

/**
 * 使用faces数组,生成wires,优先使用后端返回face的wires;去除重复的edge
 * @param faces 面渲染数据数组
 * @returns 生成的wires数组,如果生成失败就返回null
 */
const makeWires = (faces: IFace[]) => {
  const edges = new Set<string>();
  const wires: number[] = [];
  for (const face of faces) {
    const fWires = face['wires'];
    if (isArray(fWires)) {
      if (fWires.length > 0) {
        // 使用 循环 是因为使用 push(...face.wires)等方法，
        // 会在 face.wires 过长时出现 Maximum call stack size exceeded
        for (const wire of fWires) {
          wires.push(wire); // 默认后端传过来的就是没有重复的
        }
      } else {
        // 后端没有传wires,那么就用facets创建wires
        const facets = face.facets;
        if (isArray(facets) && facets.length > 0) {
          for (const f of facets) {
            if (isArray(f) && f.length === 3) {
              for (let i = 0; i < 3; i++) {
                // 三角面片,三条边由(0, 1) (1, 2) (2, 0)组成
                const start = f[i];
                const end = f[(i + 1) % 3];
                if (isUniqueEdge(start, end, edges)) {
                  wires.push(start, end);
                }
              }
            }
          }
        }
      }
    } else {
      return null;
    }
  }
  return wires;
};

export { makeWires };
